﻿using System;
using System.Text;
using System.Net;
using System.IO;
using SimpleHttpFramework.Http.Response;
using SimpleHttpFramework.Http.Request;

namespace SimpleHttpFramework {
	public class Server {
		private int _port = 8080;
		private readonly HttpListener _httpListener;
		private Router _router;

		public event Action<HttpRequest> OnHttpRequest;
		public event Action<HttpRequest> OnHttpGet;
		public event Action<HttpRequest> OnHttpPost;
		public event Action OnServerRunning;
		public event Action OnServerRun;

		public Server ()
		{
			this._httpListener = new HttpListener ();
		}

		public Server (int port) : this ()
		{
			this._port = port;
		}

		public int Port {
			get => _port;
			set => _port = value;
		}

		public Router Router {
			get => this._router;
			set => this._router = value;
		}

		public void Run ()
		{
			// Raise Event
			OnServerRunning?.Invoke ();

			this._httpListener.Prefixes.Add ($"http://+:{this._port}/");
			this._httpListener.Start ();
			this._httpListener.BeginGetContext (new AsyncCallback (GetContext), this._httpListener);

			Console.WriteLine ($@"Listen Port: {this._port} ");

			// Raise Event
			OnServerRun?.Invoke ();

			Console.Read ();
		}

		/// <summary>
		/// <see langword="async"/> 
		/// todos:
		/// 1. HttpRequest
		/// 	+ From ContentParams to META
		/// </summary>
		/// <param name="ar">Ar.</param>
		private void GetContext (IAsyncResult ar)
		{
			var httpListener = ar.AsyncState as HttpListener;
			var context = httpListener?.EndGetContext (ar); //接收到的请求context（一个环境封装体）

			httpListener?.BeginGetContext (new AsyncCallback (GetContext), httpListener); //开始 第二次 异步接收request请求

			var request = context?.Request; //接收的request数据
			var response = context?.Response; //用来向客户端发送回复

			string rawData;
			using (var reader = new StreamReader (request?.InputStream ?? throw new NullReferenceException ())) {
				rawData = reader.ReadToEnd ();
			}

			var httpRequest = new HttpRequest {
				Path = request.RawUrl,
				Body = rawData,
				Method = request.HttpMethod,
				ContentEncoding = request.ContentEncoding,
				ContentType = request.ContentType,
			};

			// Console.WriteLine($@"接收Web请求，Http方法：{request.HttpMethod}，RawURL={request.RawUrl}");

			//Raise Event
			OnHttpRequest?.Invoke (httpRequest);
			switch (request.HttpMethod.ToLower ()) {
			case "get":
				OnHttpGet?.Invoke (httpRequest);
				break;
			case "post":
				OnHttpPost?.Invoke (httpRequest);
				break;
			}

			var httpResponse = this._router.ContainsUrl (request.RawUrl)
				? this._router [request.RawUrl] (httpRequest)
				: new HttpResponseNotFound ();

			response.StatusCode = httpResponse.StatusCode;
			response.ContentType = httpResponse.ContentType;
			response.ContentEncoding = httpResponse.ContentEncoding;
			response.Cookies = httpResponse.Cookies;

			//发送回复
			using (var output = new StreamWriter (response.OutputStream)) {
				output.Write (httpResponse.Content);
			}
		}
	}
}